[#ftl]
[@define "agile._ComponentMixin" "agile._Contained,agile._MetadataMixin"]	
	category:null
	,widgetName:null
	,shortName:""
	,agileWidgetName:null
	,parameters:null	
	,widgetsInTemplate:true	
	,moveable:true
	,sortAxis:"xy"
	,_selected:false
	//,templateString: null	
	 ,constructor: function(){
//		 console.log(this.declaredClass,"[agile._ComponentMixin]:constructor....",arguments);
//		this.declaredClass = this.constructor.prototype.declaredClass;
//		this._metadata = {};		
//		console.error(this.declaredClass,"agile._Component:constructor");
		
		this.metadata("widgetClass",this.declaredClass);			
		this.metadata("category",this.category);
		this.metadata("moveable",true);
//		this.metadata("parameters",{});
//		this.metadata("style",{});
		this.metadata("style.position","absolute");
		this.metadata("anchor",{left:0,top:0});
		
		//TODO:move to the MetatadataMixin
		//only execute once for all instances to initialize the attribute labels
//		var prototype = this.constructor.prototype;
//		if(!prototype._initialized){
//			prototype._initialized = true;			
//			var attributes = this.attributes;		
//			for(var name in attributes){
//				//if(attributes[name].ignored || attributes[name].ignore()) continue;				
//				if(!attributes[name].name){
//					attributes[name].name = name;
//				}
//				if(!attributes[name].label){
//					attributes[name].label = name;
//				}
//				if(attributes[name].label.indexOf("i18n_") == 0){
//					var key = attributes[name].label.replace("i18n_","");
//					attributes[name].label = agile.i18n(key,null,true);
//					attributes[name].tooltip = agile.i18nTooltip(key,null,true);
//				}			
//			}
		
//			console.log(this.declaredClass,"prototype.attributes=", attributes);
//		}
		
		if(this.agileWidgetName == null){
			this.agileWidgetName = this.widgetName;
		}
		this.metadata("widgetName",this.widgetName);
		this.metadata("agileWidgetName",this.agileWidgetName);

		if(this.metadata("parameters.wid")){
			this.metadata("id",this.metadata("parameters.wid"));	
		}else{
			this.metadata("id",this.createId());
			this.metadata("parameters.wid",this.metadata("id"));
		}
		
		this.metadata("jsId",this.metadata("id"));
		
//		this.watch(function(name,newValue,oldValue){
//			//hovering ,active 
//			//console.log(this.declaredClass,name+" is changed from " + newValue+" to " +oldValue);
//		});
		
//		//console.log(this.declaredClass,"agile._Component:metadata:",this._metadata);
//		//console.log(this.declaredClass,"agile._Component:constructor() is called");			
	}	

	,init:function(){
		if(this._initComponentMixin){
			return true;
		}
		this._initComponentMixin = true;
		this.own(	
			on(this.domNode,"dblclick",lang.hitch(this,function(evt){
				evt.stopPropagation();
				if(!this.metadata("moveable") &&!this._selected){
					this.onSelected();			
					topic.publish("agile.widget.selected",this);
				}else{
					this.parent.onSelected();
					topic.publish("agile.widget.selected",this.parent);
				}
			}))	
//			,on(this.domNode,"click",lang.hitch(this,function(evt){
//				//console.log(this.declaredClass,"click",evt);
//				evt.stopPropagation();			
//	//			if(mouse.isLeft(evt)){//left mouse click
//					if(this.metadata("moveable") &&!this._selected){
//						this.onSelected();			
//						topic.publish("agile.widget.selected",this);
//					}
//	//			}						
//			}))
			,on(this.domNode,"mousedown",lang.hitch(this,function(evt){
					evt.stopPropagation();
					if(mouse.isRight(evt)){	
						var offset = {left: evt.offsetX,top: evt.offsetY};				
						topic.publish("agile.widget.selectedTarget",this,offset);						
					}else if(mouse.isLeft(evt)){						
						if(!this._selected){
							this.onSelected();			
							topic.publish("agile.widget.selected",this);
						}
					}
			}))
		);
		
		this.subscribe("agile.widget.selected",function(widget){
			if(this._selected && widget && this !== widget && this.parent != widget.parent){
				this.onDeselected();
			}
		});		
		
		this.subscribe("agile.debug.command",function(action){
			if(this._selected){
				switch(action){
				case "metadata":
						console.log(this.declaredClass,this.getDescription(),"metadata=",this.metadata());
					break;
				case "html":
					console.log(this.declaredClass,this.getDescription(),"html=",this.toHtml(true,0,"dojo"));
					break;
				}
			}
		});
	}	
	,computeSize:function(){
		if(this.delegate){
			style.set(this.delegate.domNode,{width:this.metadata("style.width"),height:this.metadata("style.height")});
			style.set(this.domNode,{width:"auto",height:"auto"});
		}else{
			style.set(this.domNode,{width:this.metadata("style.width"),height:this.metadata("style.height")});
		}		
	}
	/*create a shadow mockup, the changes on mockup will synchronize to the shadow mockup, a mockup can have multiple shadows*/
	,createShadow:function(){
		//TODO:
	}	
	/*clone a mockup, the cloned mockup has no linkage to the mockup after clone*/
	,clone:function(){		
		
		var divNode = construct.create("div",{
			innerHTML:this.toHtml({
						cascade:true
						,indentCount:0
						,sourceType:"agile"
						,ignoreParams:{"wid":true}
					})
			});
		parser.parse(divNode);
		return registry.byNode(divNode.firstChild);
	}
	[@method "onDeselected"/]
	,onDeselected:function(evt){
		if(domClass.contains(this.domNode,"agileSelected")){
			domClass.remove(this.domNode,"agileSelected");
		}
		this._selected = false;
	}
	[@method "onSelected"/]
	,onSelected:function(evt){
		//console.log(this.parent.declaredClass,"@isSingleSelectMode=",this.parent.isSingleSelectMode());
		//de-select parent and siblings
		if(this.parent){
			this.parent.onDeselected();	
			if(this.parent.isSingleSelectMode()){
				array.forEach(this.parent.getSelectedChildren(),function(c){
					c.onDeselected();
		        });
			}
		}
		//de-select all children
		if(this.isContainer){
			array.forEach(this.getSelectedChildren(),function(c){
				c.onDeselected();
	        });
		}
		
		domClass.add(this.domNode,"agileSelected");	
		this._selected = true;		
//		console.log(this.declaredClass,"#agileSelected=",domClass.contains(this.domNode,"agileSelected"));
	}

	,getContainerNode:function(){
		return this.containerNode;
	}
	,resetInlineEditBox:function(inlineEditBox,eventHandlers){
		aspect.after(inlineEditBox,"edit",lang.hitch(this,function(){
			var editWidget = inlineEditBox.wrapperWidget.editWidget;
			if(!editWidget._initialized){
				on(editWidget, "keyDown", function(evt){
					if(evt.keyCode != keys.CTRL){
						evt.stopPropagation();
					}
				});
				on(editWidget, "keyUp", function(evt){
					if(evt.keyCode != keys.CTRL){
						evt.stopPropagation();
					}
				});			
				if(eventHandlers){
					for(var e in eventHandlers){
						on(editWidget, e, this, eventHandlers[e]);	
					}
				}
				editWidget._initialized = true;
			}
			style.set(editWidget.domNode,"width",this.metadata("style.width"));
			style.set(editWidget.domNode,"height",this.metadata("style.height"));
			
			editWidget.reset1("value",editWidget.get("value").replace(/<br\/>/g,"\n"));			
		}));
	}
	
	,isOptional:function(){
		//true if this widget can be removed from the prototype
		return true;
	}

[/@]	

[@define "agile._Component" "_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin,agile._ComponentMixin"]
//	postMixInProperties:function(){
////		if(this.__postMixined){
////			return ;
////		}
////		this.__postMixined = true;
//		console.log(this.declaredClass,"[agile._Component] postMixInProperties...");
//		// summary: convert the parameters and styles passed by html and merge them into this._metadata
////		//console.log(this.declaredClass,"agile._Component:postMixInProperties() is called. parameters:",this.parameters);
////		//console.log(this.declaredClass,"agile._Component:postMixInProperties() is called. templateString:\n",this.templateString);
//		this.mixInMetadata();//TODO use mixinMetadata(params,node)
//		//this.templateString = lang.replace(this.templateString,lang.mixin({},this._metadata));
//		this.templateString = lang.replace(this.templateString,lang.mixin(agile.i18nValues(this.templateString,this),this._metadata));
//				
////		console.log(this.declaredClass,"agile._Component:postMixInProperties() is called. ###templateString:\n",this.templateString);
////		//console.log(this.declaredClass,"agile._Component:postMixInProperties() is called. @@@templateString:\n",this.templateString);
//		this.own(aspect.after(this,"init",lang.hitch(this,"applyParameterStyle")));
//	}
[/@]	
